In [1]:
import numpy as np

Exercise 12.1

Create a class to represent vectors of arbitrary length and which is initialised with a list of values, e.g.:

x = MyVector([0, 2, 4])

Equip the class with methods that:

  1. Return the length of the vector
  2. Compute the norm of the vector $\sqrt{x \cdot x}$
  3. Compute the dot product of the vector with another vector

Test your implementation using two vectors of length 3. To help you get started, a skeleton of the class is provided below. Don't forget to use self where necessary.


In [2]:
class MyVector:
    def __init__(self, x):
        self.x = x
        
    # Return length of vector
    def size(self):
        return len(self.x)
    
    # This allows access by index, e.g. y[2]
    def __getitem__(self, index):
        return self.x[index]

    # Return norm of vector
    def norm(self):
        squared_norm = 0
        for el in self.x:
            squared_norm += el*el
        return np.sqrt(squared_norm)
    
    # Return dot product of vector with another vector
    def dot(self, other):
        # Check if vector have the same length
        if self.size() == other.size():
            # Initialize product
            prod = 0
            # Add the product element by element to the total
            for i in range(self.size()):
                prod += self[i]*other[i]
        else:
            raise ValueError('Vector must be of the same length')
        return prod

In [3]:
# Test cases
x = MyVector([3, 4, 0])
y = MyVector([1, 2, 6])
z = MyVector([1, 2])

print(x.size()) # 3
print(y.size()) # 3
print(x.norm()) # 5
print(y.norm()) # square root of 41
print(x.dot(y)) # 11
print(x.dot(z)) # Error


3
3
5.0
6.40312423743
11
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-008f79db6c4a> in <module>()
      9 print(y.norm()) # square root of 41
     10 print(x.dot(y)) # 11
---> 11 print(x.dot(z)) # Error

<ipython-input-2-b60889fd1511> in dot(self, other)
     28                 prod += self[i]*other[i]
     29         else:
---> 30             raise ValueError('Vector must be of the same length')
     31         return prod

ValueError: Vector must be of the same length

Exercise 12.2

  1. Create a class for holding a student record entry. It should have the following attributes:
    • Surname
    • Forename
    • Birth year
    • Tripos year
    • College
    • CRSid (optional field)
  2. Equip your class with the method 'age' that returns the age of the student
  3. Equip your class with the method '__repr__' such using print on a student record displays with the format

    Surname: Bloggs, Forename: Andrea, College: Churchill
  4. Equip your class with the method __lt__(self, other) so that a list of record entries can be sorted by (surname, forename). Create a list of entries and test the sorting. Make sure you have two entries with the same surname.

Hint: To get the current year:


In [4]:
import datetime
year = datetime.date.today().year
print(year)


2017

In [5]:
class Students:
    # We have 6 attributes, CRSid is optional (default value set to None)
    def __init__(self, surname, forename, birthYear, triposYear, college, CRSid = None):
        self.surname = surname
        self.forename = forename
        self.birthYear = birthYear
        self.triposYear = triposYear
        self.college = college
        self.CRSid = CRSid
    
    def __repr__(self):
        "Print the student in the format Surname: surname, Forename: forename, College: college"
        return 'Surname: {}, Forename: {}, College: {}'.format(self.surname, self.forename, self.college)
    
    def age(self):
        "Return the age of the student subtracting the year of birth from the current year"
        return datetime.date.today().year - self.birthYear
    
    def __lt__(self, other):
        """Return true if a student's surname is before (in alphabetical order) another student's surname;
            if the surnames are equal do the same with the forenames"""
        if self.surname == other.surname:
            return self.forename < other.forename
        else:
            return self.surname < other.surname

In [6]:
# Test cases
stud0 = Students('Bella' ,'Zio', 1987, 2011, 'Università degli Studi di Torino')
stud1 = Students('Nano' ,'Gongolo', 1985, 2008, 'Università degli Studi di Torino')
stud2 = Students('Nano' ,'Dotto', 1984, 2008, 'Università degli Studi di Torino')
stud3 = Students('Casto' ,'Immanuel', 1988, 2011, 'Università degli Studi di Torino')
stud4 = Students('Ciavarro' ,'Massimo', 1983, 2006, 'Università degli Studi di Torino')

print(stud0)
print(stud0.age()) # 30
print(stud0 < stud1) # True
print(stud1 < stud0) # False
print(stud2 < stud1) # True

students_list = [stud0, stud1, stud2, stud3, stud4]
print('List:')
print(students_list)
print('Sorted list:')
students_list.sort()
print(students_list)


Surname: Bella, Forename: Zio, College: Università degli Studi di Torino
30
True
False
True
List:
[Surname: Bella, Forename: Zio, College: Università degli Studi di Torino, Surname: Nano, Forename: Gongolo, College: Università degli Studi di Torino, Surname: Nano, Forename: Dotto, College: Università degli Studi di Torino, Surname: Casto, Forename: Immanuel, College: Università degli Studi di Torino, Surname: Ciavarro, Forename: Massimo, College: Università degli Studi di Torino]
Sorted list:
[Surname: Bella, Forename: Zio, College: Università degli Studi di Torino, Surname: Casto, Forename: Immanuel, College: Università degli Studi di Torino, Surname: Ciavarro, Forename: Massimo, College: Università degli Studi di Torino, Surname: Nano, Forename: Dotto, College: Università degli Studi di Torino, Surname: Nano, Forename: Gongolo, College: Università degli Studi di Torino]